import * as koa from "koa";
import {ResponseInterface, SuccessResponse, ErrorResponse} from '../interface/responseInterface';

/**
 * base controller
 */
export default class Base {
    public request :koa.Request;
    public response: koa.Response;
    public session:Object = {};
    public ctx : koa.Context;
    
    protected constructor(ctx) {
        if (new.target === Base) {
            throw new Error('控制器基类不能实例化调用, 只能继承.');
        }
        this.request = ctx.request;
        this.response = ctx.response;
        this.ctx = ctx;
        this.session = ctx.session;
    }
    
    /**
     * 渲染模板
     * @param {string} path
     * @param {object} data
     * @returns {Promise<void>}
     */
    async render(path: string, data: object = {}) {
        if (!data._csrf) {
            data._csrf = this.ctx.csrf;
        }
        if (!data.title) {
            data.title = '';
        }

        // 菜单选中变量active
        if (!data.active) { 
            data.active = 'index';
        }
        await this.ctx.render(path, data);
    }
    
    /**
     * body getter
     */
    get body() {
        return this.ctx.body;
    }
    /**
     * body setter
     */
    set body(value) {
        this.ctx.body = value;
    }
    /**
     * get client ip
     */
    get ip() {
        return this.ctx.ip;
    }
    /**
     * get client ips
     */
    get ips() {
        return this.ctx.ips;
    }
    /**
     * get status code
     */
    get status() {
        return this.ctx.status;
    }
    /**
     * set status code
     */
    set status(status:number) {
        this.ctx.status = status;
    }
    /**
     * get content type
     */
    get type() {
        return this.ctx.type;
    }
    /**
     * set content type
     */
    set type(contentType:string) {
        this.ctx.type = contentType;
    }
    /**
     * get userAgent header
     */
    get userAgent() {
        return this.ctx.userAgent;
    }
    /**
     * get request method
     */
    get method() {
        return this.ctx.method;
    }
    
    /**
     * 是否 get 请求
     */
    get isGet() {
        return 'GET' === this.ctx.method.toUpperCase();
    }
    
    /**
     * 是否 post 请求
     */
    get isPost() {
        return 'POST' === this.ctx.method.toUpperCase();
    }
    
    /**
     * 获取分页参数
     * @return {object}
     */
    get paginate(){
        return this.ctx.paginate;
    }
    
    
    /**
     * is method
     * @param {String} method
     */
    isMethod(method:string) {
        return this.ctx.isMethod(method);
    }
   
    /**
     * 是否ajax
     */
    get isAjax():boolean {
        return this.ctx.isAjax;
    }
    
    /**
     * is jsonp request
     * @param {String} callback
     */
    isJsonp(callbackField:string) {
        return this.ctx.isJsonp(callbackField);
    }
    
    /**
     * send jsonp data
     */
    jsonp(data, callbackField) {
        return this.ctx.jsonp(data, callbackField);
    }
    
    /**
     * 发送一个json 的响应
     */
    json(data: ResponseInterface) {
        this.ctx.type = 'application/json';
        this.ctx.charset = 'charset=utf-8';
        this.body = JSON.stringify(data);
    }
    /**
     * send success data
     */
    success(params: SuccessResponse) {
        this.json({
            code: params.code || 0,
            msg : params.msg || 'success',
            data: params.data,
        })
    }
    /**
     * send fail data
     */
    fail(params: ErrorResponse) {
        this.json({
            code: params.code || 500,
            msg: params.msg || 'error'
        });
    }
    /**
     * set expires header
     * @param {Number} time
     */
    expires(time) {
        return this.ctx.expires(time);
    }
    /**
     * get query data
     * @param {String} name
     * @param {Mixed} value
     */
    get() {
        return this.request.query;
    }
    
    /**
     * 获取路由的参数
     */
    params(field: string = null) {
        if (field) {
            let params = this.ctx.params;
            return params[field];
        }
        
        return this.ctx.params || {};
    }
    
    /**
     * get query data
     * @param {String} name
     * @param {Mixed} value
     */
    query(field:string = null) {
        let query = this.get();
        if (field) {
            return query[field];
        }
        return query;
    }
    
    /**
     * 获取 post 的值
     * @param field 字段
     */
    post(field:string = null) {
        let body = this.request.body;
        if(field){
            return[field];
        }
        return body;
    }
    /**
     * get or set file data
     * @param {String} name
     * @param {Mixed} value
     */
    file(name, value) {
        return this.ctx.file(name, value);
    }
    /**
     * 设置一个cookie
     * @param {String} name
     * @param {String} value
     * @param {Object} options
     */
    setCookie(name:string, value:string, options:object = {}) {
        let defaultOptions = {
            domain: this.ctx.host,    // 写cookie所在的域名
            path: '/',              // 写cookie所在的路径
            maxAge: 10 * 60 * 1000, // cookie有效时长
            // expires: new Date('2017-02-15'),  // cookie失效时间
            httpOnly: true,  // 是否只用于http请求中获取
            overwrite: false  // 是否允许重写
        };
        
        this.ctx.cookies.set(name, value, Object.assign({}, defaultOptions, options));
    }
    
    /**
     * 获取cookie 的值
     * @param name
     */
    getCookie(name:string){
        if (!name) {
            return '';
        }
        return this.ctx.cookies.get(name);
    }
    /**
     * get or set header
     * @param {String} name
     * @param {Mixed} value
     */
    header(name, value) {
        if (value === undefined) {
            return this.ctx.header[name];
        }
        if (this.ctx.response.headersSent) {
            this.ctx.throw(`headers has already sent, url: ${this.ctx.url}`);
            return;
        }
        if (value !== undefined) {
            return this.ctx.set(name, value);
        }
    }
    
    /**
     * get referer header
     */
    referer(onlyHost) {
        return this.ctx.referer(onlyHost);
    }
    /**
     * Perform a 302 redirect to `url`.
     * @param {String} url
     * @param {String} alt
     */
    redirect(url:string, alt:string = null) {
        if (alt) {
            this.ctx.redirect(url, alt);
        } else {
            this.ctx.redirect(url);
        }
        return false;
    }
    
    /**
     * download
     * @param {String} filepath
     * @param {String} filename
     */
    download(filepath, filename) {
        return this.ctx.download(filepath, filename);
    }
}
